#coding=utf8
import re
from utils.importUtils import import_module
from ws_setting import core_logger, ALIAS_MAPPING
from core.ws_response import Response, Text

DEFAULT_KEY = "default" # 当请求参数没有加入需要执行的方法信息时候 执行此key对应的方法
ROOT_KEY = "root"       # 所有请求方法所对应的module名称
MAPPING_KEY = "mapping" # 用户自定义的方法映射，可以讲调用的方法写入请求参数中， 根据用户配置mapping找到真正需要执行的方法

class ExecutedMethodFilter:
    def before_process(self, session, *args, **kargs):
        """
            决定需要处理的方法
        """
        
        _specified = kargs.get("method", None)
        if _specified :
            session.process_function = SpecifiedObtainFunction(session, **kargs).execFunc()
            del kargs["method"]
            return 
        
        if not session.closed:
            session.process_function = MatchObtainFunction(session, **kargs).execFunc()
        else:
            session.process_function = CloseObtainFunction(session, **kargs).execFunc()


    def after_process(self, session, responses, *args, **kargs):
        if not hasattr(responses, "__iter__"):
            responses = (responses,)
        """
            根据返回的response进行处理
            从各种response对象中获得响应信息和发送对象
        """
        if not responses:
            core_logger.info(" no response ")
            responses = tuple()

        for res in responses:
            to = res.to if hasattr(res, "to") else ""
            if not isinstance(res, Response):
                res = Text(res)
            data = res.data if hasattr(res, "data") else ""
            session.request = None
            session.commands.append({"to": to, "data": data, "handle": res.handle, "async": res.async})


def addModule(context):
    gkeys = globals().keys()
    if context not in gkeys:
        _module = import_module(context)
        globals()[context] = _module
        core_logger.debug("add module {}".format(context))


class ObtainFunction:
    def __init__(self, session, **kargs):
        self.data = session.request.get_data()

        self._definition = session.app_container.url_definition(session.url)

        if not self._definition:
            raise ValueError("没有找到匹配的上下文")


        addModule(session.context)

        self._func = self.handle(self._definition, **kargs)

    def execFunc(self):
        _root = self._definition(ROOT_KEY)
        if type(self._func) != list:
            self._func = [self._func]

        if self._func and _root:
            for singe_func in self._func:
                self.full_func_str = _root + "." + singe_func
                if hasattr(self, "full_func_str") and self.full_func_str:
                    try:
                        return eval(self.full_func_str)
                    except AttributeError as ae:
                        _spilted_str = self.full_func_str.split(".")
                        core_logger.error("not foud attribute %s in module %s" % (".".join(_spilted_str[0:-1]), _spilted_str[-1]))


class MatchObtainFunction(ObtainFunction):
    def handle(self, conf, **kargs):
        core_logger.debug("########### in MatchObtainFunction handle method ##########")
        if type(self.data) != list:
            self.data = [self.data]

        res_func = []
        for _data in self.data:
            if _data and _data.get(ALIAS_MAPPING, None):
                # get mapping name
                func_name = _data.get(ALIAS_MAPPING)

                for func_rule, func_str in conf(MAPPING_KEY):
                    if re.search(func_rule, func_name) and type(func_str) == str:
                        res_func.append(re.sub(func_rule, func_str, func_name))
            else:
                # canot find ALIAS_MAPPING ,so use default mothod that user defined 
                res_func.append(conf(DEFAULT_KEY))
        return res_func

class CloseObtainFunction(ObtainFunction):
    def handle(self, conf, **kargs):
        core_logger.debug("########### in CloseObtainFunction handle method ##########")
        return conf("onclose")

class SpecifiedObtainFunction(ObtainFunction):
    def handle(self, conf, **kargs):
        core_logger.debug("########### in SpecifiedObtainFunction handle method ##########")
        specified = kargs.get("method", None)
        if specified:
            core_logger.debug("execute method %s in paramater" % specified)
            return conf(specified)
        else:
            core_logger.warn("not found key 'method' in paramater")
